package com.jdk.demo.reflect.clazz;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.util.Arrays;

public class ArrayDemo {

	/**
	 * 这个是我们创建的最终目标数组
	 */
	private static String R = "java.math.BigInteger[] bi = {123,234,345}";
	private static final String[] S = new String[]{"123", "234", "345"};

	public static void main(String[] args) throws Exception {
		// 需要注意的是，java.lang.reflect.Array中的Setter和Getter方法如果越界操作数组元素，会抛出ArrayIndexOutOfBoundsException，通过Setter设置和数组初始化时候的组件类型不一致的元素会抛出IllegalArgumentException
		Class<BigInteger> componentType = BigInteger.class;
		Object arrayObject = Array.newInstance(componentType, 3);
		for (int i = 0; i < S.length; i++) {
			String each = S[i];
			Constructor<BigInteger> constructor = componentType.getConstructor(String.class);
			BigInteger value = constructor.newInstance(each);
			Array.set(arrayObject, i, value);
		}
		Object[] result = (Object[]) arrayObject;
		System.out.println(String.format("%s[] = %s", componentType, Arrays.toString(result)));
		int length = Array.getLength(arrayObject);
		System.out.println("Length = " + length);
		for (int i = 0; i < length; i++) {
			System.out.println(String.format("index = %d,value = %s", i, Array.get(arrayObject, i)));
		}
		Class<?> arrayObjectClass = arrayObject.getClass();
		System.out.println("Is array type:" + arrayObjectClass.isArray());
		// 获取数组元素(组件)类型
		System.out.println("Component type:" + arrayObjectClass.getComponentType());

		// 因为Java泛型擦除的问题，实际上我们使用Array#newInstance方法只能得到一个Object类型的结果实例，其实这个结果实例的类型就是ComponentType[]，这里只是返回了它的父类(Object)类型实例，因此我们可以直接强转，例如：
		String[] strArray = (String[]) Array.newInstance(String.class, 3);

		// 获取数组类型：
		// 在非反射方式下，我们可以通过数组实例.class通过class字面量直接获取数组类型，例如：
		Class stringArrayClass = String[].class;
		
		// 反射条件下，可以通过Class.forName()获取数组类型，但是调用此方法的时候有个限制，类名必须使用JVM可以识别的签名形式，就是[L${ComponentType};，注意Class.forName()无法获取原始类型(如int、boolean)的类型，例如：
		// 不能漏了左边的[L和右边的;
		Class stringArrayClass2 = Class.forName("[Ljava.lang.String;");

		// 下面这样做会抛出ClassNotFoundException
		// Class intClass1 = Class.forName("I");
		// Class intClass2 = Class.forName("int");
	}

}
